package com.vehicle.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.Arrays;

@Aspect
@Component
@Slf4j
public class ControllerLogAspect {
    private final ObjectMapper objectMapper = new ObjectMapper();
    @Pointcut("execution(public * com.vehicle.controller..*.*(..))")
    public void pointcut() {}

    @Around("pointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();

        // 获取请求信息
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = null;
        if (attributes != null) {
            request = attributes.getRequest();
        }

        // 获取方法信息
        String className = joinPoint.getTarget().getClass().getSimpleName();
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();

        // 记录请求开始信息

        if (request != null) {
            log.info("=== Controller请求开始 ===");
            log.info("请求URL: {} {}", request.getMethod(), request.getRequestURI());
            log.info("执行方法: {}.{}", className, methodName);
            log.info("方法参数: {}", formatArgs(args));
        }



        Object result;
        try {
            // 执行目标方法
            result = joinPoint.proceed();

            // 计算执行时间
            long executionTime = System.currentTimeMillis() - startTime;

            if (result != null) {
                // 记录响应信息
                log.info("方法返回: {}", formatResult(result));
                log.info("执行耗时: {}ms", executionTime);
                log.info("=== Controller请求结束 ===");
            }



            return result;

        } catch (Exception e) {
            long executionTime = System.currentTimeMillis() - startTime;
            log.error("方法执行异常: {}", e.getMessage());
            log.error("执行耗时: {}ms", executionTime);
            log.error("=== Controller请求异常结束 ===\n");
            throw e;
        }
    }

    /**
     * 格式化参数为JSON字符串
     */
    private String formatArgs(Object[] args) {
        if (args == null || args.length == 0) {
            return "无参数";
        }

        try {
            // 过滤掉一些不需要序列化的参数类型
            Object[] filteredArgs = Arrays.stream(args)
                    .filter(arg -> arg != null && !isExcludedType(arg))
                    .toArray();

            if (filteredArgs.length == 0) {
                return "无有效参数";
            }

            return objectMapper.writeValueAsString(filteredArgs);
        } catch (Exception e) {
            return "参数序列化失败: " + Arrays.toString(args);
        }
    }

    /**
     * 格式化返回结果为JSON字符串
     */
    private String formatResult(Object result) {
        if (result == null) {
            return "null";
        }

        try {
            return objectMapper.writeValueAsString(result);
        } catch (Exception e) {
            return "返回值序列化失败: " + result;
        }
    }

    /**
     * 判断是否为需要排除的参数类型
     */
    private boolean isExcludedType(Object arg) {
        return arg instanceof HttpServletRequest
                || arg instanceof jakarta.servlet.http.HttpServletResponse
                || arg.getClass().getName().contains("MultipartFile");
    }
}
